class Transitions < Application
  before :find_transition, :exclude => [ :new, :create, :index ]

  def show
    #temporary fix
    case content_type
    when :html
      if @transition.incoming_places.size > 0
        render :status => 200, :layout => false
      else
        redirect(url(:transition, @transition) + "/tokens")
      end
    when :pnml
      @transition.to_pnml
    end
  end

  def update
    @transition.update_attributes!(params["transition"])
    ""
  end

  def show_token_comb
    provides :html
    
    if @case # /transition/:id/case/:case_id
      #search for one combination of tokens corresponding to given case
      @requested_tokens = @transition.active_combinations(:case => @case).first || []
    else # /transition/:id/tokens/:tokens
      @requested_tokens = params[:tokens].split(/[\/;]/).collect{|id| Token.find(id)} rescue []
    end
    
    @case = @requested_tokens.collect{|token| token.case}.compact.first
    
    if @transition.kind_of?(PNEngine::RefererTransition)
      
      uri = case @transition.refer_type.downcase
      when 'url'
        @transition.refer_to
      when 'xpath'
        doc = REXML::Document.new(@requested_tokens.first.value)
        #TODO expr return REXML::Attribute, Text or Node
        REXML::XPath.first(doc, @transition.refer_to)
        raise "Not implemented yet"
      when 'locator'
        @requested_tokens.first.values[@transition.refer_to]
      end
      
      self.status = 302
      headers['Location'] = uri
      return ""
    else
      render :status => 200, :layout => false
    end
  end
  
  def fire
    only_provides :xml
    
    #POST on referer transitions => forbidden
    if @transition.kind_of?(PNEngine::RefererTransition)
      self.status = 403
      return ""
      # for debugging purposes
    elsif @transition.kind_of?(PNEngine::AutomaticTransition) || @transition.kind_of?(PNEngine::SendTransition)
      @transition.trigger_fire
      #TODO redirect to petrinets/id/case/id?
      redirect @transition.petrinet.url
      return ""
    end
	
    begin
      if @case
        tokens_to_consume = @transition.active_combinations(:case => @case).first || []
      else
        tokens_to_consume = params[:tokens].split(/[\/;]/).collect{|id| Token.find(id)} rescue []
      end
      
      attributes = request.raw_post.empty? ? nil : {:value => REXML::Document.new(request.raw_post).root.elements[1].to_s}
      produced_tokens = @transition.fire(tokens_to_consume, attributes, :notify_following_transitions => true)

      self.status = 302
      case_id = @case || (produced_tokens + tokens_to_consume).first.case_id
      headers['Location'] = Merb::Config[:root] + url(:petrinet, @transition.petrinet) + "/case/#{case_id}"
      render_then_call "" do
        @transition.notify_following_transitions
      end
    rescue Exception => e
      Merb.logger.error(e)
      Merb.logger.error(e.backtrace.join("\n"))
  
      self.status = 500
      return ""
    end
  end
  
  private
  def find_transition
    @transition = PNEngine::Transition.find(params[:id] || params[:transition_id])
    @case = PNEngine::Case.find(params[:case_id]) if params[:case_id]
  end
end
